package com.mccree.config;

import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {
    /**
     *  创建 ShiroFilterFactoryBean
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        factoryBean.setSecurityManager(securityManager);
        /**
         * 添加shiro内置过滤器，常用的有如下过滤器：
         * anon:无需认证
         * authc:必须认证才能访问
         * user:如果使用了remember才能访问
         * perms:拥有了某个资源权限才可以访问
         * role:拥有某个角色权限才可以访问
         */
        Map<String,String> filterMap = new LinkedHashMap<>();
        //authc会跳过授权逻辑把下面所有的都干掉，即不生效
//        filterMap.put("/user/*","authc");
        filterMap.put("/user/add","perms[user:add]");
        filterMap.put("/user/update","perms[user:update]");

        factoryBean.setFilterChainDefinitionMap(filterMap);

        factoryBean.setLoginUrl("/toLogin");

        factoryBean.setUnauthorizedUrl("/noAuth");


        return factoryBean;
    }


    /**
     * 创建 DefaultWebSecurityManager
      */

    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm realm
            ,@Qualifier("sessionManager")DefaultWebSessionManager sessionManager
            ,@Qualifier("rememberMeManager")CookieRememberMeManager rememberMeManager){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(realm);
        securityManager.setSessionManager(sessionManager);
        securityManager.setRememberMeManager(rememberMeManager);
        return securityManager;
    }

    /**
     * 重写DefaultWebSessionManager会话管理去除Jsessionid,
     * @return
     */
    @Bean(name = "sessionManager")
    public DefaultWebSessionManager getDefaultWebSessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }

    /**
     * 创建 realm 对象
      * @param matcher
     * @return
     */
    @Bean(name = "userRealm")
    public UserRealm getRealm(@Qualifier("matcher")HashedCredentialsMatcher matcher){
        UserRealm realm = new UserRealm();
        realm.setCredentialsMatcher(matcher);
        return realm;
    }

    /**
     * 创建HashedCredentialsMatcher
     * @return
     */
    @Bean(name = "matcher")
    public HashedCredentialsMatcher getHashedCredentialsMatcher(){
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("MD5");
        return matcher;
    }

    /**
     * 配置shiro的Dialect,方言，用于 thymeleaf 和 shiro 标签配合使用
     * @return
     */
    @Bean
    public ShiroDialect getShiroDialect(){
        return new ShiroDialect();
    }
    /**
     * 设置cookie
     */
    @Bean(name = "cookie")
    public SimpleCookie getSimpleCookie(){
        //和前端remember保持一致
        SimpleCookie cookie = new SimpleCookie("remember");
        //设置cookie过期时间
        cookie.setMaxAge(86400);
        return cookie;
    }
    /**
     * cookie管理对象
     */
    @Bean(name = "rememberMeManager")
    public CookieRememberMeManager getCookieRememberMeManager(@Qualifier("cookie")SimpleCookie cookie){
        CookieRememberMeManager rememberMeManager = new CookieRememberMeManager();
        rememberMeManager.setCookie(cookie);
        rememberMeManager.setCipherKey(Base64.decode("6ZmI6I2j3Y+R1aSn5BOlAA=="));
        return rememberMeManager;
    }
}
